package com.googlecode.cswish.util.lucene;

import java.io.IOException;
import java.io.Reader;

import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.util.AttributeSource;

public class UserIdTokenizer extends Tokenizer {
	  
	  private static final int DEFAULT_BUFFER_SIZE = 256;

	  private boolean done = false;
	  private int finalOffset;
	  private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
	  private OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
	  private UserIdAttribute userIdAtt = addAttribute(UserIdAttribute.class);
	  
	  public UserIdTokenizer(Reader input) {
	    this(input, DEFAULT_BUFFER_SIZE);
	  }

	  public UserIdTokenizer(Reader input, int bufferSize) {
	    super(input);
	    termAtt.resizeBuffer(bufferSize);
	  }

	  public UserIdTokenizer(AttributeSource source, Reader input, int bufferSize) {
	    super(source, input);
	    termAtt.resizeBuffer(bufferSize);
	  }

	  public UserIdTokenizer(AttributeFactory factory, Reader input, int bufferSize) {
	    super(factory, input);
	    termAtt.resizeBuffer(bufferSize);
	  }
	  
	  @Override
	  public final boolean incrementToken() throws IOException {
	    if (!done) {
	      clearAttributes();
	      done = true;
	      int upto = 0;
	      char[] buffer = termAtt.buffer();
	      while (true) {
	        final int length = input.read(buffer, upto, buffer.length-upto);
	        if (length == -1) break;
	        upto += length;
	        if (upto == buffer.length)
	          buffer = termAtt.resizeBuffer(1+buffer.length);
	      }
	      
	      // check the '|' flag
	      int termLen = 0;
	      for (; termLen < upto; termLen++) {
	    	  if (buffer[termLen] == '|') {
	    		  break;
	    	  }
	      }
	      // check the next '|' flag
	      int userIdEnd = termLen + 1;
	      for (; userIdEnd < upto; userIdEnd++) {
	    	  if (buffer[userIdEnd] == '|') {
	    		  break;
	    	  }
	      }
	      
	      termAtt.setLength(termLen);
	      finalOffset = correctOffset(termLen);
	      offsetAtt.setOffset(correctOffset(0), finalOffset);
	      String sId = new String(buffer, termLen + 1, userIdEnd - termLen - 1);
	      userIdAtt.setUserId(Long.valueOf(sId));
	      String sMessageId = new String(buffer, userIdEnd + 1, upto - userIdEnd - 1);
	      userIdAtt.setMessageId(Long.valueOf(sMessageId));
	      return true;
	    }
	    return false;
	  }
	  
	  @Override
	  public final void end() {
	    // set final offset 
	    offsetAtt.setOffset(finalOffset, finalOffset);
	  }

	  @Override
	  public void reset(Reader input) throws IOException {
	    super.reset(input);
	    this.done = false;
	  }
	}
